package com.yz.order.mq;

import com.rabbitmq.client.Channel;
import com.yz.common.constant.MQConstants;
import com.yz.common.resp.BaseResponse;
import com.yz.model.entity.order.Order;
import com.yz.order.service.OrderService;
import com.yz.order.service.feign.OrderUserFeign;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;

/**
 * Created With IntelliJ IDEA.
 * Descriptions:
 * <p>
 * User:Mr.Du
 * Date:2024/4/9
 * Time:13:43
 */
@Slf4j
@Component
public class UserMessageConsumer {

    @Resource
    private OrderService orderService;

    private Integer MAX_RETRY_COUNT = 3;

    private Integer cnt = 0;

    @Resource
    private OrderUserFeign orderUserFeign;

    @SneakyThrows
    @RabbitListener(queues = {MQConstants.USER_QUEUE_NAME}, ackMode = "MANUAL")
    public void receiveMessage(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
        try{
            this.handleMessage(message, channel, deliveryTag);
        }catch (Exception e){
            log.error("消息消费失败user", e);
            if(++cnt > MAX_RETRY_COUNT){
                channel.basicNack(deliveryTag, false, false);
            }else{
                channel.basicNack(deliveryTag, false, true);
            }
        }
    }

    /**
     * 处理消息，尝试为指定订单进行充值。
     *
     * @param message 包含订单号的字符串消息。
     * @param channel AMQP消息通道，用于应答消息处理结果。
     * @param deliveryTag 消息的唯一标识，用于确认或拒绝消息。
     * @throws IOException 当与消息队列的通信发生问题时抛出。
     * @throws RuntimeException 当消息为空、订单不存在或充值失败时抛出。
     */
    @Transactional
    void handleMessage(String message, Channel channel, long deliveryTag) throws IOException {
        log.info("receiveMessage message = {}", message);
        if(StringUtils.isBlank(message)){
            channel.basicNack(deliveryTag, false, false); // 消息为空，拒绝消息并不重试
            throw new RuntimeException("消息为空");
        }
        long tradeNo = Long.parseLong(message);
        log.info("tradeNo: {}", tradeNo);
        Order order = orderService.getById(tradeNo); // 根据订单号获取订单信息
        log.info("order-user = {}", order);
        if(order == null){
            channel.basicNack(deliveryTag, false, false); // 订单不存在，拒绝消息并不重试
            throw new RuntimeException("订单不存在");
        }
        // 调用远程服务进行充值
        BaseResponse<Boolean> booleanBaseResponse = orderUserFeign.reChargeAmount(order.getUid(), order.getAmount() * 10);
        log.info("booleanBaseResponse = {}", booleanBaseResponse);
        if(booleanBaseResponse.getCode() != 0){
            channel.basicNack(deliveryTag, false, false); // 充值失败，拒绝消息并不重试
            throw new RuntimeException("充值失败");
        }
        channel.basicAck(deliveryTag, false); // 充值成功，确认消息
    }

}